package cn.com.nes.site.service.project.impl;

import cn.com.nes.common.exception.IllegalBusinessException;
import cn.com.nes.common.util.CopyUtils;
import cn.com.nes.common.util.OssUtil;
import cn.com.nes.common.util.RegexUtils;
import cn.com.nes.common.util.XzqhUtils;
import cn.com.nes.mybatis.agent.crm.entity.Customer;
import cn.com.nes.mybatis.agent.crm.entity.Opportunity;
import cn.com.nes.mybatis.agent.crm.entity.OpportunityDeviceModel;
import cn.com.nes.mybatis.agent.ope.entity.SaleOrderInfo;
import cn.com.nes.mybatis.agent.project.entity.ProjectCustomerRelationship;
import cn.com.nes.mybatis.agent.project.entity.ProjectLog;
import cn.com.nes.mybatis.agent.project.entity.TProject;
import cn.com.nes.mybatis.agent.project.entity.TProjectScheduling;
import cn.com.nes.mybatis.agent.project.mapper.TProjectMapper;
import cn.com.nes.mybatis.agent.system.entity.Company;
import cn.com.nes.mybatis.agent.system.entity.TParam;
import cn.com.nes.mybatis.callcenter.entity.WorkOrderInfo;
import cn.com.nes.site.entity.PageData;
import cn.com.nes.site.entity.bo.crm.sale.SaleOrderPageBO;
import cn.com.nes.site.entity.bo.project.*;
import cn.com.nes.site.entity.em.DeleteEnum;
import cn.com.nes.site.entity.em.company.CompanyIdEnum;
import cn.com.nes.site.entity.em.crm.customer.CustomerNatureEnum;
import cn.com.nes.site.entity.em.crm.opportunity.OpportunityStageEnum;
import cn.com.nes.site.entity.em.crm.opportunity.OpportunityTypeEnum;
import cn.com.nes.site.entity.em.project.ProjectRelationDataTypeEnum;
import cn.com.nes.site.entity.em.project.ProjectRelationTypeEnum;
import cn.com.nes.site.entity.em.project.ProjectStatusEnum;
import cn.com.nes.site.entity.em.project.ProjectTypeEnum;
import cn.com.nes.site.entity.vo.crm.SaveCustomerVo;
import cn.com.nes.site.entity.vo.project.DelProjectImportCustomersVO;
import cn.com.nes.site.entity.vo.project.ProjectAcceptanceVO;
import cn.com.nes.site.entity.vo.project.ProjectPageVO;
import cn.com.nes.site.event.project.ProjectEventPublisher;
import cn.com.nes.site.modules.opportuntiy.OpportunityBusiness;
import cn.com.nes.site.service.crm.customer.CrmCustomerService;
import cn.com.nes.site.service.crm.customer.CustomerHouseService;
import cn.com.nes.site.service.crm.customer.bo.CustomerPageBO;
import cn.com.nes.site.service.crm.customer.bo.SaveOpportunityBO;
import cn.com.nes.site.service.crm.customer.dto.CustomerDTO;
import cn.com.nes.site.service.crm.flow.CrmFlowTableRelationshipService;
import cn.com.nes.site.service.crm.opportunity.CrmOpportunityService;
import cn.com.nes.site.service.crm.opportunity.OpportunityDeviceModelService;
import cn.com.nes.site.service.crm.opportunity.dto.OpportunityDeviceModelDTO;
import cn.com.nes.site.service.crm.order.SaleOrderInfoService;
import cn.com.nes.site.service.crm.order.dto.SaleOrderInfoDTO;
import cn.com.nes.site.service.product.GGoodsService;
import cn.com.nes.site.service.project.ProjectCustomerRelationshipService;
import cn.com.nes.site.service.project.ProjectLogService;
import cn.com.nes.site.service.project.ProjectSchedulingService;
import cn.com.nes.site.service.project.TProjectService;
import cn.com.nes.site.service.project.dto.GetTProjectByOrderId;
import cn.com.nes.site.service.project.dto.ProjectCustomerRelationCountDTO;
import cn.com.nes.site.service.project.dto.ProjectRelationshipDTO;
import cn.com.nes.site.service.project.dto.TProjectDTO;
import cn.com.nes.site.service.system.company.BusinessCompanyService;
import cn.com.nes.site.service.system.dict.TParamService;
import cn.com.nes.site.service.system.region.XzqhService;
import cn.com.nes.site.service.workOrder.WorkOrderService;
import cn.com.nes.site.service.workOrder.dto.CustomerRefusalWorkOrderInfoDTO;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.net.URLDecoder;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class TProjectServiceImpl extends ServiceImpl<TProjectMapper, TProject> implements TProjectService {

    @Resource
    TParamService tParamService;

    @Resource
    ProjectSchedulingService projectSchedulingService;

    @Resource
    BusinessCompanyService businessCompanyService;

    @Resource
    SaleOrderInfoService saleOrderInfoService;

    @Resource
    ProjectCustomerRelationshipService projectCustomerRelationshipService;

    @Resource
    CrmCustomerService crmCustomerService;

    @Resource
    CrmOpportunityService crmOpportunityService;

    @Resource
    private OpportunityBusiness opportunityBusiness;

    @Resource
    ProjectLogService projectLogService;

    @Resource
    WorkOrderService workOrderService;

    @Resource
    CustomerHouseService customerHouseService;

    @Resource
    GGoodsService gGoodsService;

    @Resource
    private ProjectEventPublisher projectEventPublisher;

    @Resource
    protected OpportunityDeviceModelService opportunityDeviceModelService;

    @Resource
    private XzqhService xzqhService;

    @Resource
    private CrmFlowTableRelationshipService crmFlowTableRelationshipService;

    @Override
    public TProject getProjectDetail(Long projectId) {
        return this.baseMapper.selectById(projectId);
    }

    @Override
    public TProjectDTO getProjectDetail(ProjectQueryBO bo) throws Exception {
        TProjectDTO projectDTO = new TProjectDTO();
        BeanUtils.copyProperties(this.getProjectDetail(bo.getId()), projectDTO);

        // 查询项目排期
        TProjectScheduling projectScheduling = projectSchedulingService.getOne(projectDTO.getUuid());
        if (ObjectUtil.isNotNull(projectScheduling)) {
            projectDTO.setServiceStartTime(projectScheduling.getStartTime());
            projectDTO.setServiceEndTime(projectScheduling.getEndTime());
        }

        // 查询项目类别字典
        Map<String, TParam> serviceModeParamMap = tParamService.getMapValueIsKey("91");

        // 查询项目类别字典
        Map<String, TParam> projectTypeParamMap = tParamService.getMapValueIsKey("92");
        // 查询项目状态字典
        Map<String, TParam> projectStatusParamMap = tParamService.getMapValueIsKey("90");
        // 查询项目等级字典
        Map<String, TParam> projectLevelParamMap = tParamService.getMapValueIsKey("93");
        // 存在服务模式字典， 赋值服务模式名称
        if (!serviceModeParamMap.isEmpty()) {
            projectDTO.setServiceModeName(serviceModeParamMap.getOrDefault(projectDTO.getServiceMode(), new TParam())
                    .getName());
        }
        // 存在项目类别字典，赋值类别名称
        if (!projectTypeParamMap.isEmpty()) {
            projectDTO.setProjectTypeName(projectTypeParamMap.getOrDefault(projectDTO.getProjectType(), new TParam())
                    .getName());
        }
        // 存在项目状态字典，赋值状态名称
        if (!projectStatusParamMap.isEmpty()) {
            projectDTO.setProjectStatusName(projectStatusParamMap.getOrDefault(projectDTO.getProjectStatus(), new TParam())
                    .getName());
        }
        // 存在项目等级字典，赋值等级名称
        if (!projectLevelParamMap.isEmpty()) {
            projectDTO.setProjectLevelName(projectLevelParamMap.getOrDefault(projectDTO.getProjectLevel(), new TParam())
                    .getName());
        }
        // 查询公司名称
        projectDTO.setCompanyName(bo.getUserInfo().getCompanyName());
        List<ProjectCustomerRelationship> list = projectCustomerRelationshipService.getRelationshipsExcludeMain(projectDTO.getUuid());
        HashMap<String, Integer> hashMap = workOrderService.getAuditedCount(bo.getId());
        projectDTO.setAuditedCount(hashMap.get("auditedCount"));
        projectDTO.setCount(list.size());
        projectDTO.setNotAuditedCount(hashMap.get("notAuditedCount"));
        // 获取图片URL
        getProjectImageURL(projectDTO);

        List<OpportunityDeviceModel> deviceModels = opportunityDeviceModelService.getDeviceModels(projectDTO.getOpportunityUuid());
        projectDTO.setAllowDeviceModels(CollUtil.isNotEmpty(deviceModels) ? CopyUtils.copyList(deviceModels, OpportunityDeviceModelDTO.class) : Collections.emptyList());

        return projectDTO;
    }

    private void getProjectImageURL(TProjectDTO projectDTO) {
        if (StrUtil.isNotEmpty(projectDTO.getImages())) {
            String[] imageArray = projectDTO.getImages().split(";", -1);
            List<String> imageList = new ArrayList<String>();
            for (int k = 0; k < imageArray.length; k++) {
                String str = imageArray[k];
                imageList.add(OssUtil.getImgSignURL(str, 0));
            }
            projectDTO.setImageList(imageList);
        }
    }

    /**
     * 更新项目的负责人信息和商机信息
     * @param projectId        项目id
     * @param masterCustomerId 负责人id
     * @param opportunityUuid  商机id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateProjectById(Long projectId, String masterCustomerId, String opportunityUuid) throws Exception {
        TProject tProject = new TProject();
        tProject.setId(projectId);
        tProject.setCustomerUuid(masterCustomerId);
        tProject.setOpportunityUuid(opportunityUuid);

        Integer rows = this.baseMapper.updateById(tProject);
        if (rows != 1) {
            throw new Exception("更新项目负责人/商机信息失败,导入中断!");
        }
    }

    /**
     * 保存项目信息
     * @param bo 保存项目信息模型
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public TProject projectSave(ProjectSaveBO bo) throws Exception {
        // 新增或更新客户
        CustomerDTO customerDTO = createOrUpdateCustomer(bo);
        bo.setCustomerUuid(customerDTO.getUuid());

        // 新增商机
        if (StrUtil.isEmpty(bo.getOpportunityUuid())) {
            Opportunity opportunity = saveOpportunityInfo(bo);
            log.info("生成主客户商机... {}", opportunity.getUuid());
            bo.setOpportunityUuid(opportunity.getUuid());
        }

        // 构建、保存项目
        TProject project = buildAndSaveProject(bo);
        bo.setProjectId(project.getUuid());

        // 处理项目客户关系。客户uuid 和商机uuid 查询有没有这个关系，然后再判断是新增还是删除旧的后再新增。
        handleProjectCustomerRelationship(bo);

        // 记录项目操作记录
        logAfterPorjectOperate(bo);

        // 记录项目排期信息
        if (ObjectUtil.isNotNull(bo.getServiceStartTime()) && ObjectUtil.isNotNull(bo.getServiceEndTime())) {
            schedulingProject(bo);
        }

        return project;
    }

    private TProject buildAndSaveProject(ProjectSaveBO bo) throws Exception {
        log.debug("构建、保存项目信息....");
        TProject project = new TProject();
        BeanUtils.copyProperties(bo, project);
        project.setJsondata(URLDecoder.decode(bo.getJsondata(), "UTF-8"));
        if (bo.isAddProject()) {
            project.setCompanyId(bo.getOperateUserCompanyId());
            project.setUuid(UUID.randomUUID().toString());
            project.setCreateuid(bo.getOperateUserId());
            project.setCreatetime(bo.getOperateDate());
            project.setProjectStatus(ProjectStatusEnum._01.getKey());
            // 新增时，项目编号根据项目类型+时间戳 自动生成
            project.setProjectId(ProjectTypeEnum.getKey(bo.getProjectType()) + System.currentTimeMillis());
        }
        // 传入 serviceStartTime 和 serviceEndTime 且 项目状态为待排期， 需要将项目状态更改为待分配
        if (ObjectUtil.isNotNull(bo.getServiceStartTime()) && ObjectUtil.isNotNull(bo.getServiceEndTime()) && project.getProjectStatus()
                .equals(ProjectStatusEnum._01.getKey())) {
            project.setProjectStatus(ProjectStatusEnum._02.getKey());
        }
        project.setModifyuid(bo.getOperateUserId());
        project.setModifytime(bo.getOperateDate());

        if (ObjectUtil.isNotEmpty(bo.getDeviceModels())) {
            project.setDeviceModels(String.join(";", bo.getDeviceModels()));
        }
        project.setCustomerUuid(bo.getCustomerUuid());
        project.setOpportunityUuid(bo.getOpportunityUuid());
        this.saveOrUpdate(project);
        bo.setUuid(project.getUuid());
        return project;
    }

    private CustomerDTO createOrUpdateCustomer(ProjectSaveBO bo) throws Exception {
        log.debug("新增/更新客户数据....");
        SaveCustomerVo saveCustomerVo = new SaveCustomerVo();
        BeanUtils.copyProperties(bo, saveCustomerVo);
        saveCustomerVo.setUuid(null);
        if (StringUtils.isNotEmpty(bo.getCustomerUuid())) {
            saveCustomerVo.setUuid(bo.getCustomerUuid());
        }
        saveCustomerVo.setCustomerName(bo.getContact());
        saveCustomerVo.setPhone(bo.getContactPhone());
        //        saveCustomerVo.setCustomerCode(bo.getCustomerUuid()); // 客户编号不能赋值为客户id
        saveCustomerVo.setCompanyId(bo.getUserInfo().getCompanyId());
        saveCustomerVo.setXzqhdm(bo.getAreaCode());
        if (ProjectTypeEnum.BUSINESS.getKey().equals(bo.getProjectType())) {
            saveCustomerVo.setCustomerNature(CustomerNatureEnum._enterprise.getKey());
        } else if (ProjectTypeEnum.GOVERNMENT.getKey().equals(bo.getProjectType())) {
            saveCustomerVo.setCustomerNature(CustomerNatureEnum._government.getKey());
        } else {
            saveCustomerVo.setCustomerNature(CustomerNatureEnum._personal.getKey());
        }
        saveCustomerVo.setCustomerLevel(bo.getProjectLevel());
        saveCustomerVo.setAddress(bo.getProjectAddress());
        return crmCustomerService.customerSave(saveCustomerVo.convertToBo());
    }

    private void handleProjectCustomerRelationship(ProjectSaveBO bo) throws Exception {
        String projectUuid = bo.isAddProject() ? null : bo.getUuid();
        ProjectCustomerRelationship mainProjectRelationship = projectCustomerRelationshipService.getRelationshipsForMain(projectUuid, bo.getOpportunityUuid());
        if (bo.isAddProject() && ObjectUtil.isNull(mainProjectRelationship)) {
            // 保存项目客户关系表
            ProjectCustomerRelationship projectCustomerRelationship = new ProjectCustomerRelationship();
            projectCustomerRelationship.setBusinessId(bo.getOpportunityUuid());
            //如果是前端添加的项目客户那么导入用户id和主id是一个id
            projectCustomerRelationship.setCustomerId(bo.getCustomerUuid());
            projectCustomerRelationship.setMainCustomerId(bo.getCustomerUuid());
            projectCustomerRelationship.setMainBusinessId(bo.getOpportunityUuid());
            projectCustomerRelationship.setProjectUuid(bo.getUuid());
            projectCustomerRelationship.setMainFlag(ProjectRelationTypeEnum.MAIN.getKey());
            projectCustomerRelationship.setImportBatch(bo.getOperateTimeStamp());
            projectCustomerRelationship.setDataType(ProjectRelationDataTypeEnum.MANUAL_OPERATION.getKey());
            projectCustomerRelationship.setDeleted(DeleteEnum._0.getKey());
            projectCustomerRelationship.setGmtCreateId(bo.getOperateUserId());
            projectCustomerRelationship.setGmtCreate(bo.getOperateDate());
            projectCustomerRelationshipService.save(projectCustomerRelationship);
            if (!ProjectTypeEnum.GOVERNMENT.getKey().equals(bo.getProjectType())) {
                projectCustomerRelationship.setMainFlag(ProjectRelationTypeEnum.OTHER.getKey());
                projectCustomerRelationshipService.save(projectCustomerRelationship);
            }
        } else {
            projectCustomerRelationshipService.updateRelationshipsByMainCustomerId(bo.getUuid(), bo.getOpportunityUuid(), bo.getOperateUserId(), bo.getOperateDate());
        }
        log.debug("处理项目客户关系....");
    }

    private void schedulingProject(ProjectSaveBO bo) throws Exception {
        ProjectSchedulingSaveBO projectSchedulingSaveBo = new ProjectSchedulingSaveBO();
        BeanUtils.copyProperties(bo, projectSchedulingSaveBo);
        projectSchedulingSaveBo.setProjectUuid(bo.getUuid());
        projectSchedulingSaveBo.setDepartmentId(bo.getDepartmentId());
        projectSchedulingSaveBo.setServiceStartTime(bo.getServiceStartTime());
        projectSchedulingSaveBo.setServiceEndTime(bo.getServiceEndTime());
        projectSchedulingService.saveProjectScheduling(projectSchedulingSaveBo);
        log.debug("记录项目排期....");
    }

    private void logAfterPorjectOperate(ProjectSaveBO bo) {
        if (!bo.isAddProject()) {
            return;
        }

        ProjectLog projectLog = new ProjectLog();
        projectLog.setLinkId(bo.getUuid());
        projectLog.setLinkType("1");
        projectLog.setTitle("新建项目");
        projectLog.setRemark("创建项目： " + bo.getProjectName());
        projectLog.setCreateuid(bo.getOperateUserId());
        projectLog.setCreatetime(bo.getOperateDate());
        projectEventPublisher.publishEvent(projectLog);
        log.debug("新增项目操作日志....");
    }

    /**
     * 查询项目分页列表
     * @param vo 项目分页查询模型
     * @return
     */
    @Override
    public Page<TProjectDTO> projectPage(ProjectPageVO vo) throws Exception {
        Page<TProjectDTO> resultPage = new Page<>(vo.getPageid(), vo.getPagesize());
        resultPage.setTotal(0);
        resultPage.setCurrent(vo.getPageid());
        resultPage.setRecords(new ArrayList<>());

        // 如果是创今公司账号 - 不需要以行政区划过滤
        if (CompanyIdEnum.NES_COMPANY.getKey().equals(vo.getOperateUserCompanyId())) {
            vo.setFilterByAreaCode(false);
        }
        // 判断是否需要以行政区划过滤
        if (vo.getFilterByAreaCode()) {
            // 如果没配置任何行政区划,就不用查询项目分页
            if (CollectionUtil.isEmpty(vo.getOperateUserAreaCodeSet())) {
                log.info("没配置任何行政区划,不用查询项目分页,操作人昵称:{},操作人id{}", vo.getOperateNickName(), vo.getOperateUserId());
                return resultPage;
            }
            // 如果配置的行政区划包含86 - 不按行政区划过滤
            if (!vo.getOperateUserAreaCodeSet().contains("86")) {
                // 获取行政区划的全部子集
                vo.setProjectAreaCodeSet(xzqhService.getChildAreaCodesByParentAreaCodeSet(vo.getOperateUserAreaCodeSet(), true));
            }
        }

        // 准备分页参数
        Page<TProject> page = new Page<>(vo.getPageid(), vo.getPagesize());
        List<TProject> projects = this.baseMapper.projectPage(page, vo);
        List<TProjectDTO> projectDTOS = CopyUtils.copyList(projects, TProjectDTO.class);
        if (CollUtil.isNotEmpty(projectDTOS)) {
            List<String> projectUuids = projectDTOS.stream().map(TProjectDTO::getUuid).collect(Collectors.toList());
            // 查询项目排期
            List<TProjectScheduling> schedulingList = projectSchedulingService.getList(projectUuids);

            // 查询项目客户关系数量
            List<ProjectCustomerRelationCountDTO> projectCustomerRelationCountDTOList = projectCustomerRelationshipService.getCustomerCountOfProject(projectUuids);
            Map<String, ProjectCustomerRelationCountDTO> projectCustomerCountMap = new HashMap<>();
            if (CollUtil.isNotEmpty(projectCustomerRelationCountDTOList)) {
                projectCustomerCountMap.putAll(projectCustomerRelationCountDTOList.stream()
                        .collect(Collectors.toMap(ProjectCustomerRelationCountDTO::getProjectUuid, p -> p)));
            }

            // 查询项目类别字典
            Map<String, TParam> serviceModeParamMap = tParamService.getMapValueIsKey("91");
            // 查询项目类别字典
            Map<String, TParam> projectTypeParamMap = tParamService.getMapValueIsKey("92");
            // 查询项目状态字典
            Map<String, TParam> projectStatusParamMap = tParamService.getMapValueIsKey("90");
            // 查询项目等级字典
            Map<String, TParam> projectLevelParamMap = tParamService.getMapValueIsKey("93");

            // 查询公司列表
            Set<String> companyIds = projectDTOS.stream().map(TProjectDTO::getCompanyId).collect(Collectors.toSet());
            List<Company> companys = businessCompanyService.getCompanys(companyIds);

            for (TProjectDTO projectDTO : projectDTOS) {
                // 存在服务模式字典， 赋值服务模式名称
                if (!serviceModeParamMap.isEmpty()) {
                    projectDTO.setServiceModeName(serviceModeParamMap.getOrDefault(projectDTO.getServiceMode(), new TParam())
                            .getName());
                }
                // 存在项目类别字典，赋值项目类别名称
                if (!projectTypeParamMap.isEmpty()) {
                    projectDTO.setProjectTypeName(projectTypeParamMap.getOrDefault(projectDTO.getProjectType(), new TParam())
                            .getName());
                }
                // 存在项目状态字典，赋值项目状态名称
                if (!projectStatusParamMap.isEmpty()) {
                    projectDTO.setProjectStatusName(projectStatusParamMap.getOrDefault(projectDTO.getProjectStatus(), new TParam())
                            .getName());
                }
                // 存在项目等级字典，赋值项目等级名称
                if (!projectLevelParamMap.isEmpty()) {
                    projectDTO.setProjectLevelName(projectLevelParamMap.getOrDefault(projectDTO.getProjectLevel(), new TParam())
                            .getName());
                }

                // 存在公司，赋值公司名称
                if (!companys.isEmpty()) {
                    Map<String, Company> companysMap = companys.stream()
                            .collect(Collectors.toMap(Company::getCompanyid, company -> company));
                    projectDTO.setCompanyName(companysMap.getOrDefault(projectDTO.getCompanyId(), new Company())
                            .getCompanyname());
                }

                // 存在项目排期，添加排期时间
                if (CollUtil.isNotEmpty(schedulingList)) {
                    Map<String, TProjectScheduling> schedulingMap = projectSchedulingService.convertToMapOfKeyIsProjectUuid(schedulingList);
                    projectDTO.setServiceStartTime(schedulingMap.getOrDefault(projectDTO.getUuid(), new TProjectScheduling())
                            .getStartTime());
                    projectDTO.setServiceEndTime(schedulingMap.getOrDefault(projectDTO.getUuid(), new TProjectScheduling())
                            .getEndTime());
                }

                getProjectImageURL(projectDTO);

                // 设置设备类型
                if (StrUtil.isNotEmpty(projectDTO.getDeviceModels())) {
                    List<String> deviceModelList = Arrays.stream(projectDTO.getDeviceModels().split(";"))
                            .collect(Collectors.toList());
                    projectDTO.setDeviceModelList(gGoodsService.getDeviceModels(projectDTO.getCompanyId(), deviceModelList));
                }

                // 设置项目客户数量
                if (projectCustomerCountMap.containsKey(projectDTO.getUuid())) {
                    projectDTO.setCustomerTotal(projectCustomerCountMap.get(projectDTO.getUuid()).getCustomerCount());
                }
            }
        }

        //        Page<TProjectDTO> resultPage = new Page<>(vo.getPageid(), vo.getPagesize());
        resultPage.setTotal(page.getTotal());
        resultPage.setCurrent(page.getCurrent());
        resultPage.setRecords(projectDTOS);

        return resultPage;
    }

    /**
     * 查询未派单的项目分页列表
     * @param bo 未派单的项目分页模型
     * @return
     */
    @Override
    public Page<TProjectDTO> dispatchedProjectPage(DispatchedProjectBO bo) throws Exception {
        // 准备分页参数
        Page<TProjectDTO> page = new Page<>(bo.getPageid(), bo.getPagesize());
        page.setRecords(new ArrayList<>());

        // 如果是创今公司账号 - 不需要以行政区划过滤
        if (CompanyIdEnum.NES_COMPANY.getKey().equals(bo.getOperateUserCompanyId())) {
            bo.setFilterByAreaCode(false);
        }
        // 判断是否需要以行政区划过滤
        if (bo.getFilterByAreaCode()) {
            // 如果没配置任何行政区划,就不用查询项目分页
            if (CollectionUtil.isEmpty(bo.getOperateUserAreaCodeSet())) {
                log.info("没配置任何行政区划,不用查询工单分页,操作人昵称:{},操作人id{}", bo.getOperateUserName(), bo.getOperateUserId());
                return page;
            }
            // 如果配置的行政区划包含86 - 不按行政区划过滤
            if (!bo.getOperateUserAreaCodeSet().contains("86")) {
                // 获取行政区划的全部子集
                bo.setProjectAreaCodeSet(xzqhService.getChildAreaCodesByParentAreaCodeSet(bo.getOperateUserAreaCodeSet(), true));
            }
        }

        bo.setAreaCode(XzqhUtils.getRegionCodePrefix(bo.getAreaCode()));
        List<TProjectDTO> projectDTOS = this.baseMapper.getdispatchedProjectPage(page, bo);

        // 查询项目类别字典
        Map<String, TParam> serviceModeParamMap = tParamService.getMapValueIsKey("91");
        // 查询项目类别字典
        Map<String, TParam> projectTypeParamMap = tParamService.getMapValueIsKey("92");
        // 查询项目状态字典
        Map<String, TParam> projectStatusParamMap = tParamService.getMapValueIsKey("90");
        // 查询项目等级字典
        Map<String, TParam> projectLevelParamMap = tParamService.getMapValueIsKey("93");
        for (TProjectDTO projectDTO : projectDTOS) {
            // 存在服务模式字典， 赋值服务模式名称
            if (!serviceModeParamMap.isEmpty()) {
                projectDTO.setServiceModeName(serviceModeParamMap.getOrDefault(projectDTO.getServiceMode(), new TParam())
                        .getName());
            }
            // 存在项目类别字典，赋值项目类别名称
            if (!projectTypeParamMap.isEmpty()) {
                projectDTO.setProjectTypeName(projectTypeParamMap.getOrDefault(projectDTO.getProjectType(), new TParam())
                        .getName());
            }
            // 存在项目状态字典，赋值项目状态名称
            if (!projectStatusParamMap.isEmpty()) {
                projectDTO.setProjectStatusName(projectStatusParamMap.getOrDefault(projectDTO.getProjectStatus(), new TParam())
                        .getName());
            }
            // 存在项目等级字典，赋值项目等级名称
            if (!projectLevelParamMap.isEmpty()) {
                projectDTO.setProjectLevelName(projectLevelParamMap.getOrDefault(projectDTO.getProjectLevel(), new TParam())
                        .getName());
            }

            // 政府项目要查询导入名单的总和
            if ("03".equals(projectDTO.getProjectType())) {
                List<ProjectCustomerRelationship> relationshipsExcludeMain = projectCustomerRelationshipService.getRelationshipsExcludeMain(projectDTO.getUuid());
                if (CollUtil.isNotEmpty(relationshipsExcludeMain)) {
                    List<String> opportunities = relationshipsExcludeMain.stream()
                            .map(ProjectCustomerRelationship::getBusinessId)
                            .collect(Collectors.toList());
                    projectDTO.setSystemNumber(saleOrderInfoService.getSystemNumberByOpportunityList(opportunities));
                }
            } else {
                if (ObjectUtil.isNull(projectDTO.getSaleOrderId())) {
                    projectDTO.setSystemNumber(0);
                    continue;
                }
                SaleOrderInfoDTO orderDetatil = saleOrderInfoService.getOrderDetatil(projectDTO.getSaleOrderId());
                if (ObjectUtil.isNotNull(projectDTO.getSaleOrderId()) && ObjectUtil.isNotNull(orderDetatil) && CollUtil.isNotEmpty(orderDetatil.getPriceSheetList())) {
                    projectDTO.setSystemNumber(orderDetatil.getPriceSheetList().size());
                }
            }

            // 查询导入名单已派单个数
            projectDTO.setDispatchedCount(Integer.parseInt(workOrderService.getDispatchedCount(projectDTO.getId()) + ""));

            // 查询导入名单工单个数
            List<WorkOrderInfo> workOrderList = workOrderService.getWorkOrderList(projectDTO.getId(), null);
            if (CollUtil.isNotEmpty(workOrderList)) {
                projectDTO.setWorkOrderCount(workOrderList.size());
            }
        }
        page.setRecords(projectDTOS);

        return page;
    }

    /**
     * 查询导入用户分页列表
     * @param bo
     * @return
     */
    @Override
    public Page<ProjectRelationshipDTO> getProjectImportCustomers(ProjectImportCustomersPageBO bo) throws Exception {
        ProjectCustomerRelationshipPageBO projectCustomerRelationshipPageBo = new ProjectCustomerRelationshipPageBO();
        bo.setAreaCode(XzqhUtils.getRegionCodePrefix(bo.getAreaCode()));
        BeanUtils.copyProperties(bo, projectCustomerRelationshipPageBo);
        // 处理派单情况
        if (ObjectUtil.isNotNull(projectCustomerRelationshipPageBo.getIsDispatched()) || ObjectUtil.isNotNull(projectCustomerRelationshipPageBo.getAudited())) {
            List<String> customerIdList = workOrderService.getCustomerIdListByDispatched(projectCustomerRelationshipPageBo.getIsDispatched(), projectCustomerRelationshipPageBo.getAudited());
            projectCustomerRelationshipPageBo.setCustomerIdList(customerIdList);
        }
        Page<ProjectRelationshipDTO> page = projectCustomerRelationshipService.getRelationshipsExcludeMain(projectCustomerRelationshipPageBo);
        // 查询系统个数
        for (ProjectRelationshipDTO projectRelationshipDTO : page.getRecords()) {
            SaleOrderInfo saleOrderInfo = saleOrderInfoService.getSaleOrder(projectRelationshipDTO.getOpportunityUuid());
            if (ObjectUtil.isNotEmpty(saleOrderInfo)) {
                SaleOrderInfoDTO saleOrderInfoDTO = saleOrderInfoService.getPriceMastersAndDetails(saleOrderInfo.getId());
                projectRelationshipDTO.setSystemNumber(saleOrderInfoDTO.getPriceSheetList().size());
                projectRelationshipDTO.setSaleOrderInfoDTO(saleOrderInfoDTO);
                projectRelationshipDTO.setImportBatchDate(new Date(projectRelationshipDTO.getImportBatch()));

                if (CollUtil.isNotEmpty(saleOrderInfoDTO.getPriceSheetList())) {
                    // 根据销售单查询工单信息，获取服务时间，如果获取不到，设置为项目排期的时间。
                    WorkOrderInfo workOrderInfo = workOrderService.getWorkOrder(saleOrderInfoDTO.getPriceSheetList()
                            .get(0)
                            .getId());
                    if (ObjectUtil.isNotNull(workOrderInfo) && ObjectUtil.isNotNull(workOrderInfo.getAgreedDoorstepTimeStart()) && ObjectUtil.isNotNull(workOrderInfo.getAgreedDoorstepTimeEnd())) {
                        projectRelationshipDTO.setServiceStartTime(workOrderInfo.getAgreedDoorstepTimeStart());
                        projectRelationshipDTO.setServiceEndTime(workOrderInfo.getAgreedDoorstepTimeEnd());
                        projectRelationshipDTO.setWorkOrderId(workOrderInfo.getId().toString());
                        projectRelationshipDTO.setAudited(workOrderInfo.getAudited());
                        projectRelationshipDTO.setWorkOrderState(workOrderInfo.getStatus().toString());
                    } else {
                        TProjectScheduling projectScheduling = projectSchedulingService.getOne(projectRelationshipDTO.getProjectUuid());
                        if (ObjectUtil.isNotNull(projectScheduling)) {
                            projectRelationshipDTO.setServiceStartTime(projectScheduling.getStartTime());
                            projectRelationshipDTO.setServiceEndTime(projectScheduling.getEndTime());
                        }
                    }
                }
            }
        }

        // 查询客户有没有已拒单的工单
        if (CollectionUtil.isNotEmpty(page.getRecords())) {
            List<String> customerIdList = page.getRecords()
                    .stream()
                    .filter(n -> ObjectUtil.isNotNull(n) && StrUtil.isNotBlank(n.getCustomerId()))
                    .map(ProjectRelationshipDTO::getCustomerId)
                    .distinct()
                    .collect(Collectors.toList());

            // 查询当前项目下的全部工单id
            Set<Long> workOrderIdSet = new HashSet<>();
            TProject projectInfoByUuid = this.getProjectByUuid(bo.getProjectUuid());
            if (ObjectUtil.isNotNull(projectInfoByUuid)) {
                workOrderIdSet = crmFlowTableRelationshipService.getWorkOrderIdSetByProjectId(projectInfoByUuid.getId());
            }

            List<CustomerRefusalWorkOrderInfoDTO> customerRefusalWorkOrderInfoList = workOrderService.getCustomerRefusalWorkOrderInfo(customerIdList, workOrderIdSet);
            boolean flag = CollectionUtil.isNotEmpty(customerRefusalWorkOrderInfoList);
            page.getRecords().forEach(n -> {
                if (flag && ObjectUtil.isNotNull(n) && StrUtil.isNotBlank(n.getCustomerId())) {
                    CustomerRefusalWorkOrderInfoDTO customerRefusalWorkOrderInfo = customerRefusalWorkOrderInfoList.stream()
                            .filter(m -> m.getCustomerId().equals(n.getCustomerId()))
                            .findFirst()
                            .orElse(null);
                    if (ObjectUtil.isNotNull(customerRefusalWorkOrderInfo)) {
                        n.setNeedSupport(ObjectUtil.isNotNull(customerRefusalWorkOrderInfo.getFlag()) ? customerRefusalWorkOrderInfo.getFlag() : Boolean.FALSE);
                        // 查询客户的工单个数
                        n.setWorkOrderCount(customerRefusalWorkOrderInfo.getWorkOrderCount());
                        // 查询客户的派单个数
                        n.setDispatchedCount(customerRefusalWorkOrderInfo.getDispatchedCount());
                        // 查询客户的拒单次数
                        n.setRejectionCount(customerRefusalWorkOrderInfo.getRejectionCount());
                    }
                }
            });
        }

        return page;
    }

    @Deprecated
    @Override
    public PageData dispatchedOrderPageForProject(DispatchedProjectBO dispatchedProjectBO) throws Exception {
        TProject project = getProjectByUuid(dispatchedProjectBO.getProjectUuid());
        List<ProjectCustomerRelationship> relationshipsExcludeMain;
        if ("03".equals(project.getProjectType())) {
            // 先通过项目uuid，查询项目下的所有导入客户
            relationshipsExcludeMain = projectCustomerRelationshipService.getRelationshipsExcludeMain(project.getUuid());
        } else {
            relationshipsExcludeMain = projectCustomerRelationshipService.getRelationshipsForMain(project.getUuid());
        }

        List<String> opportunityIds = relationshipsExcludeMain.stream()
                .map(ProjectCustomerRelationship::getBusinessId)
                .collect(Collectors.toList());
        List<String> customerIds = relationshipsExcludeMain.stream()
                .map(ProjectCustomerRelationship::getCustomerId)
                .collect(Collectors.toList());
        // 分页查询客户，获取分页客户ID
        CustomerPageBO customerPageBo = new CustomerPageBO();
        BeanUtils.copyProperties(dispatchedProjectBO, customerPageBo);
        customerPageBo.setCustomerIds(customerIds);
        Page<Customer> page = crmCustomerService.customerPage(customerPageBo);
        List<Customer> customers = page.getRecords();
        List<String> customerIdList = customers.stream().map(Customer::getUuid).collect(Collectors.toList());

        // 查询商机列表
        QueryWrapper<Opportunity> opportunityEntityWrapper = new QueryWrapper<>();
        opportunityEntityWrapper.in("customerId", customerIdList);
        opportunityEntityWrapper.in("uuid", opportunityIds);
        List<Opportunity> opportunities = crmOpportunityService.list(opportunityEntityWrapper);
        List<String> opportunityIdList = opportunities.stream().map(Opportunity::getUuid).collect(Collectors.toList());

        // 根据分页后的客户ID，查询销售订单
        SaleOrderPageBO saleOrderPageBo = new SaleOrderPageBO();
        BeanUtils.copyProperties(dispatchedProjectBO, saleOrderPageBo);
        saleOrderPageBo.setOpportunityIds(opportunityIdList);
        Page<SaleOrderInfoDTO> orderInfoDTOPage = saleOrderInfoService.getPriceMastersAndDetails(saleOrderPageBo);
        return PageData.ok(orderInfoDTOPage, orderInfoDTOPage.getRecords());
    }

    @Override
    public TProject getProjectByUuid(String projectUuid) throws Exception {
        TProject project = this.baseMapper.getUnDeletedProjectByUuid(projectUuid);
        if (ObjectUtil.isNull(project)) {
            throw new IllegalBusinessException("项目不存在！");
        }
        return project;
    }

    /**
     * 查询项目
     * @param idOrUuid 主键ID或UUID
     * @return
     */
    @Override
    public TProject getProject(String idOrUuid) throws Exception {
        QueryWrapper<TProject> wrapper = new QueryWrapper<>();
        wrapper.eq("deleted", DeleteEnum._0.getKey());
        if (RegexUtils.containsLetter(idOrUuid)) {
            wrapper.eq("uuid", idOrUuid);
        } else {
            wrapper.eq("id", idOrUuid);
        }

        TProject project = this.getOne(wrapper);
        if (ObjectUtil.isNull(project)) {
            throw new IllegalBusinessException("项目不存在！");
        }
        return project;
    }

    @Override
    public TProject getProjectByopportunityUuid(String opportunityUuid) throws Exception {
        QueryWrapper<TProject> wrapper = new QueryWrapper<>();
        wrapper.eq("deleted", DeleteEnum._0.getKey());
        if (RegexUtils.containsLetter(opportunityUuid)) {
            wrapper.eq("opportunity_uuid", opportunityUuid);
        }
        TProject project = this.getOne(wrapper);
        if (ObjectUtil.isNull(project)) {
            return null;
        }
        return project;
    }


    @Override
    public Set<Long> getProjectIdSet(String companyId, String projectName, String projectType, String projectStatus) {
        QueryWrapper<TProject> wrapper = new QueryWrapper<>();
        wrapper.select("id");
        wrapper.eq("deleted", DeleteEnum._0.getKey());
        if (StrUtil.isNotBlank(companyId)) {
            wrapper.eq("company_id", companyId);
        }
        if (StrUtil.isNotBlank(projectName)) {
            wrapper.like("project_name", projectName);
        }
        if (StrUtil.isNotBlank(projectType)) {
            wrapper.eq("project_type", projectType);
        }
        if (StrUtil.isNotBlank(projectStatus)) {
            wrapper.eq("project_status", projectStatus);
        }

        List<TProject> projectList = this.baseMapper.selectList(wrapper);
        if (CollectionUtil.isEmpty(projectList)) {
            return new HashSet<>();
        }
        return projectList.stream().map(TProject::getId).collect(Collectors.toSet());
    }

    @Override
    public Integer projectAcceptance(ProjectAcceptanceVO vo) {
        return this.baseMapper.projectAcceptance(vo);
    }

    @Override
    public List<GetTProjectByOrderId> getTProjectByOrderId(Long workOrderId) {
        return this.baseMapper.getTProjectByOrderId(workOrderId);
    }

    // 保存商机信息
    public Opportunity saveOpportunityInfo(ProjectSaveBO bo) throws Exception {
        try {
            SaveOpportunityBO opportunityBO = new SaveOpportunityBO();
            BeanUtils.copyProperties(bo, opportunityBO);
            opportunityBO.setOpportunityStage(OpportunityStageEnum._transaction); // 默认商机成交
            opportunityBO.setOpportunityType(OpportunityTypeEnum._purchase); // 默认购买设备
            opportunityBO.setOpportunityName(bo.getProjectName() + "-商机");
            opportunityBO.setCustomerId(bo.getCustomerUuid());
            opportunityBO.setXzqhdm(bo.getAreaCode());
            opportunityBO.setProjectAddress(bo.getProjectAddress());
            opportunityBO.setPersonInCharge(bo.getContact());
            opportunityBO.setPersonInChargePhone(bo.getContactPhone());
            opportunityBO.setMemo("");
            opportunityBO.setEstimatedClosingDate(bo.getOperateDate());
            opportunityBO.setBuildNature("");
            opportunityBO.setCgfType("");
            opportunityBO.setCjfCompanyName(bo.getUserInfo().getCompanyName());
            opportunityBO.setLongitude(bo.getLongitude());
            opportunityBO.setLatitude(bo.getLatitude());
            opportunityBO.setProjectAddress(bo.getProjectAddress());
            Opportunity opportunity = opportunityBusiness.save(opportunityBO.convertToBO());
            log.info("创建客户 -> 新增个人用户商机... [{}]", opportunity.getUuid());
            return opportunity;
        } catch (Exception e) {
            log.error("保存商机信息失败,客户姓名:{},客户电话号:{},异常原因:{}", bo.getContact(), bo.getContactPhone(), e.getMessage(), e);
            throw e;
        }
    }


    /**
     * 删除项目导入客户 - 根据需求判断数据量不会很大,无需做异步处理
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer delProjectImportCustomers(DelProjectImportCustomersVO vo) throws Exception {
        log.info("开始删除导入的客户信息,入参:{}", JSON.toJSONString(vo));
        // 获取要删除的客户id列表
        List<String> customerIdList = CollectionUtil.isNotEmpty(vo.getCustomerIdList()) ? vo.getCustomerIdList() : new ArrayList<>();
        if (StrUtil.isNotBlank(vo.getXzqhdm())) {
            String xzqhdm = XzqhUtils.getRegionCodePrefix(vo.getXzqhdm());
            log.info("处理后的行政区划代码:{}", xzqhdm);
            if (StrUtil.isNotBlank(xzqhdm)) {
                // 查询当前行政区划下全部客户id
                List<String> customerIdListByXzqhdm = projectCustomerRelationshipService.getCustomerIdListByXzqhdm(vo.getProjectUuid(), xzqhdm);
                if (CollectionUtil.isNotEmpty(customerIdListByXzqhdm)) {
                    log.info("通过行政区划代码查询到的客户id列表:{}", JSON.toJSONString(customerIdListByXzqhdm));
                    customerIdList.addAll(customerIdListByXzqhdm);
                }
            }
        }
        // 去重
        customerIdList = customerIdList.stream().distinct().collect(Collectors.toList());
        // 过滤掉有工单的客户
        List<String> haveWorkOrderCustomerIdList = new ArrayList<>();
        Iterator<String> iterator = customerIdList.iterator();
        while (iterator.hasNext()) {
            String customerId = iterator.next();
            if (workOrderService.checkHaveWorkOrder(customerId)) {
                haveWorkOrderCustomerIdList.add(customerId);
                iterator.remove();
            }
        }
        log.info("有安装工单未删除成功的客户id:{}", haveWorkOrderCustomerIdList);
        log.info("最终要删除的客户id:{}", JSON.toJSONString(customerIdList));
        if (CollectionUtil.isEmpty(customerIdList)) {
            return 0;
        }
        // 开始删除客户信息
        // 1、删除客户的项目-客户关系数据
        projectCustomerRelationshipService.deleteImportCustomerByCustomerId(customerIdList, vo.getOperateUserId(), vo.getOperateDate());
        // 判断是否需要删除业务数据
        if (ObjectUtil.isNotNull(vo.getDelType()) && 1 == vo.getDelType()) {
            try {
                // 2、删除客户的销售订单数据
                saleOrderInfoService.deleteByCustomerIds(customerIdList, vo.getOperateUserId(), vo.getOperateDate());
                // 3、删除客户的商机数据
                crmOpportunityService.deleteByCustomerIds(customerIdList, vo.getOperateUserId(), vo.getOperateDate());
                // 4、删除客户的房屋数据
                customerHouseService.deleteByCustomerIds(customerIdList, vo.getOperateUserId(), vo.getOperateDate());
                // 5、删除客户数据
                crmCustomerService.deleteByIds(customerIdList, vo.getOperateUserId(), vo.getOperateDate());
            } catch (Exception e) {
                log.info("删除客户业务数据失败,异常原因:{}", e.getMessage());
            }
        }
        return customerIdList.size();
    }

    @Override
    public Long getProjectIdByUuid(String projectUuid) throws Exception {
        return this.getProjectDetail(projectUuid).getId();
    }

    @Override
    public TProjectDTO getProjectDetail(String projectUuid) throws Exception {
        QueryWrapper<TProject> wrapper = new QueryWrapper<>();
        wrapper.eq("uuid", projectUuid);
        wrapper.eq("deleted", false);
        TProject project = this.getOne(wrapper);
        if (ObjectUtil.isNull(project)) {
            throw new Exception("未查询到项目信息");
        }

        TProjectDTO projectDTO = new TProjectDTO();
        BeanUtils.copyProperties(project, projectDTO);
        return projectDTO;
    }

}
